package common

import (
	"strings"
	"unicode"
)

// 将snake命名转化为C风格命名（保持小写，去掉所有的下划线）。
func IdentToC(id string) string {
	if id == "" {
		panic("Argument \"identifier\" must not be empty")
	}

	rs := []rune(id)
	rs2 := make([]rune, 0, len(rs))
	for _, r := range rs {
		if unicode.IsSpace(r) || r == '\\' || r == '/' {
			// 跳过所有的空白符，斜线和反斜线。
			continue
		}
		if r == '_' || r == '-' {
			continue
		}

		rs2 = append(rs2, unicode.ToLower(r))
	}

	return string(rs2)
}

func IdentToUpper(id string) string {
	if id == "" {
		panic("Argument \"identifier\" must not be empty")
	}

	return strings.ToUpper(id)
}

func IdentToLower(id string) string {
	if id == "" {
		panic("Argument \"identifier\" must not be empty")
	}

	return strings.ToLower(id)
}

// 将snake命名转化为camel命名。
func IdentToCamel(id string) string {
	if id == "" {
		panic("Argument \"identifier\" must not be empty")
	}

	rs := []rune(id)
	rs2 := make([]rune, 0, len(rs))
	fw := true // 首个单词
	fc := true // 首个字母
	for _, r := range rs {
		if unicode.IsSpace(r) || r == '\\' || r == '/' {
			// 跳过所有的空白符，斜线和反斜线。
			continue
		}
		if r == '_' || r == '-' {
			fc = true
			// 发现下划线或者横线，那么第一个单词已经结束，后面的单词都不是第一个单词。
			fw = false
			continue
		} else if r == '.' {
			// 发现点号，复位标志。
			fc = true
			fw = true
			rs2 = append(rs2, '.')
			continue
		}

		if fc {
			// 首字母
			if !fw {
				// 不是第一个单词，需要转大写。
				rs2 = append(rs2, unicode.ToUpper(r))
			} else {
				// 否则转小写。
				rs2 = append(rs2, unicode.ToLower(r))
			}
			fc = false
		} else {
			// 非首字母一律转小写。
			rs2 = append(rs2, unicode.ToLower(r))
		}
	}

	return string(rs2)
}

// 将snake命名转化为Pascal命名。
func IdentToPascal(id string) string {
	if id == "" {
		panic("Argument \"identifier\" must not be empty")
	}

	rs := []rune(id)
	rs2 := make([]rune, 0, len(rs))
	fc := true
	for _, r := range rs {
		if unicode.IsSpace(r) || r == '\\' || r == '/' {
			// 跳过所有的空白符，斜线和反斜线。
			continue
		}
		if r == '_' || r == '-' {
			fc = true
			continue
		} else if r == '.' {
			fc = true
			rs2 = append(rs2, '.')
			continue
		}

		if fc {
			// 首字母，直接转大写。
			rs2 = append(rs2, unicode.ToUpper(r))
			fc = false
		} else {
			// 非首字母一律转小写。
			rs2 = append(rs2, unicode.ToLower(r))
		}
	}

	if len(rs2) >= 3 {
		// 超过2个字符的标识符需要特殊处理。
		// 如果前两个字母都是大写，需要将第一个转为小写。
		if unicode.IsUpper(rs2[0]) && unicode.IsUpper(rs2[1]) {
			rs2[0] = unicode.ToLower(rs2[0])
		}
	}

	return string(rs2)
}
